﻿using System;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using advadev.CanOpen;


namespace advadev.CanOpen.UnitTests
{

    /// <summary>
    /// Represents the network management command write transfer unit tests
    /// </summary>
    [TestClass]
    public class NetworkManagementCommandWriteTransferTest : ICanOpenObjectDictionaryContainer
    {

        #region constructor tests
        /// <summary>
        /// Constructor test
        /// </summary>
        [TestMethod]
        public void ConstructorTest()
        {
            // initialization
            NetworkManagementCommandSpecifier networkManagementCommandSpecifier = NetworkManagementCommandSpecifier.Unkown;
            NetworkManagementCommandWriteTransfer testObject = null;

            // node id out of range parameter
            try
            {
                testObject = new NetworkManagementCommandWriteTransfer(networkManagementCommandSpecifier, 0);
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException)
            {
            }
            catch
            {
                Assert.Fail();
            }
            try
            {
                testObject = new NetworkManagementCommandWriteTransfer(networkManagementCommandSpecifier, 128);
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException)
            {
            }
            catch
            {
                Assert.Fail();
            }
        }
        #endregion constructor tests


        #region master side tests
        /// <summary>
        /// Master side test
        /// </summary>
        [TestMethod]
        public void MasterSideTest()
        {
            // initialization
            byte nodeId = 103;
            UInt16 cobId = 0x100;
            NetworkManagementCommandSpecifier networkManagementCommandSpecifier = NetworkManagementCommandSpecifier.Unkown;
            NetworkManagementCommandWriteTransfer testObject = null;

            // test with start remote node command
            networkManagementCommandSpecifier = NetworkManagementCommandSpecifier.StartRemoteNode;
            testObject = new NetworkManagementCommandWriteTransfer(networkManagementCommandSpecifier, nodeId);
            testObject.Start();
            Assert.AreEqual(false, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(1, testObject.PendingSendMessages.Count);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].CanId);
            Assert.AreEqual(0x01, testObject.PendingSendMessages[0].Byte0);
            Assert.AreEqual(0x67, testObject.PendingSendMessages[0].Byte1);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte2);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte3);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte4);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte5);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte6);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte7);
            Assert.AreEqual((uint)2, testObject.PendingSendMessages[0].Length);
            testObject.ContinueAfterSendingMessages();
            Assert.AreEqual(true, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(0, testObject.PendingSendMessages.Count);

            // test with changed COB-ID
            networkManagementCommandSpecifier = NetworkManagementCommandSpecifier.StartRemoteNode;
            testObject = new NetworkManagementCommandWriteTransfer(networkManagementCommandSpecifier, nodeId, cobId);
            testObject.Start();
            Assert.AreEqual(false, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(1, testObject.PendingSendMessages.Count);
            Assert.AreEqual(cobId, testObject.PendingSendMessages[0].CanId);
            Assert.AreEqual(0x01, testObject.PendingSendMessages[0].Byte0);
            Assert.AreEqual(0x67, testObject.PendingSendMessages[0].Byte1);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte2);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte3);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte4);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte5);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte6);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte7);
            Assert.AreEqual((uint)2, testObject.PendingSendMessages[0].Length);
            testObject.ContinueAfterSendingMessages();
            Assert.AreEqual(true, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(0, testObject.PendingSendMessages.Count);
        }
        #endregion master side tests


        #region is network management command write transfer request tests
        /// <summary>
        /// Is network management command write transfer request test
        /// </summary>
        [TestMethod]
        public void IsNetworkManagementCommandWriteTransferRequestTest()
        {
            // initialization
            bool isNetworkManagementCommandWriteTransferRequest = false;
            byte nodeId = 103;
            UInt16 cobId = 0x01;
            NetworkManagementCommandSpecifier receivedNetworkManagementCommandSpecifier = NetworkManagementCommandSpecifier.Unkown;
            NetworkManagementCommandReceivedEventHandler handler = new NetworkManagementCommandReceivedEventHandler((object sender, NetworkManagementCommandReceivedEventArgs args) =>
            {
                receivedNetworkManagementCommandSpecifier = args.NetworkManagementCommandSpecifier;
            });
            NetworkManagementCommandWriteTransfer testObject = null;

            // test with valid received can open message
            isNetworkManagementCommandWriteTransferRequest = NetworkManagementCommandWriteTransfer.IsNetworkManagementCommandWriteTransfer(new CanOpenMessage(0x00, 0x01, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), nodeId, out testObject, handler);
            Assert.AreEqual(true, isNetworkManagementCommandWriteTransferRequest);
            Assert.IsNotNull(testObject);

            // test with not matsching node id
            isNetworkManagementCommandWriteTransferRequest = NetworkManagementCommandWriteTransfer.IsNetworkManagementCommandWriteTransfer(new CanOpenMessage(0x00, 0x01, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), nodeId, out testObject, cobId, handler);
            Assert.AreNotEqual(true, isNetworkManagementCommandWriteTransferRequest);
            Assert.IsNull(testObject);

            // test with wrong COB-ID
            isNetworkManagementCommandWriteTransferRequest = NetworkManagementCommandWriteTransfer.IsNetworkManagementCommandWriteTransfer(new CanOpenMessage(0x50, 0x01, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), nodeId, out testObject, cobId, handler);
            Assert.AreNotEqual(true, isNetworkManagementCommandWriteTransferRequest);
            Assert.IsNull(testObject);

            // test with handler is null
            isNetworkManagementCommandWriteTransferRequest = NetworkManagementCommandWriteTransfer.IsNetworkManagementCommandWriteTransfer(new CanOpenMessage(0x00, 0x01, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), nodeId, out testObject, null);
            Assert.AreEqual(true, isNetworkManagementCommandWriteTransferRequest);
            Assert.IsNotNull(testObject);
        }
        #endregion is network management command write transfer request tests


        #region slave side tests
        /// <summary>
        /// Slave side test
        /// </summary>
        [TestMethod]
        public void SlaveSideTest()
        {
            // initialization
            bool isNetworkManagementCommandWriteTransferRequest = false;
            byte nodeId = 103;
            UInt16 cobId = 0x01;
            NetworkManagementCommandSpecifier receivedNetworkManagementCommandSpecifier = NetworkManagementCommandSpecifier.Unkown;
            NetworkManagementCommandSpecifier networkManagementCommandSpecifier = NetworkManagementCommandSpecifier.Unkown;
            NetworkManagementCommandReceivedEventHandler handler = new NetworkManagementCommandReceivedEventHandler((object sender, NetworkManagementCommandReceivedEventArgs args) =>
            {
                receivedNetworkManagementCommandSpecifier = args.NetworkManagementCommandSpecifier;
            });
            NetworkManagementCommandWriteTransfer testObject = null;
            NetworkManagementCommandWriteTransfer masterTransfer = null;

            // test with start remote node command
            receivedNetworkManagementCommandSpecifier = CanOpen.NetworkManagementCommandSpecifier.Unkown;
            networkManagementCommandSpecifier = NetworkManagementCommandSpecifier.StartRemoteNode;
            masterTransfer = new NetworkManagementCommandWriteTransfer(networkManagementCommandSpecifier, nodeId);
            masterTransfer.Start();
            isNetworkManagementCommandWriteTransferRequest = NetworkManagementCommandWriteTransfer.IsNetworkManagementCommandWriteTransfer(masterTransfer.PendingSendMessages[0], nodeId, out testObject, handler);
            Assert.AreEqual(true, isNetworkManagementCommandWriteTransferRequest);
            Assert.IsNotNull(testObject);
            testObject.Start();
            Assert.AreEqual(networkManagementCommandSpecifier, receivedNetworkManagementCommandSpecifier);
            Assert.AreEqual(true, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(0, testObject.PendingSendMessages.Count);

            // test with changed COB-ID
            receivedNetworkManagementCommandSpecifier = CanOpen.NetworkManagementCommandSpecifier.Unkown;
            networkManagementCommandSpecifier = NetworkManagementCommandSpecifier.StartRemoteNode;
            masterTransfer = new NetworkManagementCommandWriteTransfer(networkManagementCommandSpecifier, nodeId, cobId);
            masterTransfer.Start();
            isNetworkManagementCommandWriteTransferRequest = NetworkManagementCommandWriteTransfer.IsNetworkManagementCommandWriteTransfer(masterTransfer.PendingSendMessages[0], nodeId, out testObject, cobId, handler);
            Assert.AreEqual(true, isNetworkManagementCommandWriteTransferRequest);
            Assert.IsNotNull(testObject);
            testObject.Start();
            Assert.AreEqual(networkManagementCommandSpecifier, receivedNetworkManagementCommandSpecifier);
            Assert.AreEqual(true, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(0, testObject.PendingSendMessages.Count);

            // test without handler
            receivedNetworkManagementCommandSpecifier = CanOpen.NetworkManagementCommandSpecifier.Unkown;
            networkManagementCommandSpecifier = NetworkManagementCommandSpecifier.StartRemoteNode;
            masterTransfer = new NetworkManagementCommandWriteTransfer(networkManagementCommandSpecifier, nodeId);
            masterTransfer.Start();
            isNetworkManagementCommandWriteTransferRequest = NetworkManagementCommandWriteTransfer.IsNetworkManagementCommandWriteTransfer(masterTransfer.PendingSendMessages[0], nodeId, out testObject, null);
            Assert.AreEqual(true, isNetworkManagementCommandWriteTransferRequest);
            Assert.IsNotNull(testObject);
            testObject.Start();
            Assert.AreEqual(NetworkManagementCommandSpecifier.Unkown, receivedNetworkManagementCommandSpecifier);
            Assert.AreEqual(true, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(0, testObject.PendingSendMessages.Count);
        }
        #endregion slave side tests


        #region ICanOpenObjectDictionaryContainer
        /// <summary>
        /// Gets the node id of the can open object dictionary container
        /// </summary>
        byte ICanOpenObjectDictionaryContainer.NodeId
        {
            get
            {
                return 103;
            }
        }

        /// <summary>
        /// Gets the can open object with the given index as can open data field
        /// object
        /// </summary>
        /// <param name="index">
        /// Index of the can open object to get
        /// </param>
        /// <returns>
        /// The can open object with the given index as data field object or
        /// null
        /// </returns>
        ICanOpenDataFieldObject ICanOpenObjectDictionaryContainer.GetCanOpenObject(UInt16 index)
        {
            return null;
        }

        /// <summary>
        /// Gets the can open object with the given index and sub index as can
        /// open value object
        /// </summary>
        /// <param name="index">
        /// Index of the can open object to get
        /// </param>
        /// <param name="subIndex">
        /// Sub index of the can open object to get
        /// </param>
        /// <returns>
        /// The can open object with the given index and sub index as value
        /// object or null
        /// </returns>
        ICanOpenValueObject ICanOpenObjectDictionaryContainer.GetCanOpenObject(UInt16 index, byte subIndex)
        {
            return null;
        }
        #endregion ICanOpenObjectDictionaryContainer

    }

}
